package com.tdk.wifidirectserver.socket.server

import android.util.Log
import com.tdk.common.util.SafeCloseUtil
import com.tdk.wifidirectserver.socket.SocketHandler
import com.tdk.wifidirectserver.socket.client.Client
import com.tdk.wifidirectserver.socket.client.IClientListener
import java.io.IOException
import java.net.InetSocketAddress
import java.net.ServerSocket
import java.nio.charset.Charset
import java.util.concurrent.ConcurrentHashMap


/**
 * socket服务端管理类
 * @property TAG String
 * @property mServer ServerSocket? socket服务端
 * @property mIServerListener IServerActionListener? server回调接口
 * @property mAcceptThread AcceptThread? 轮询等待客户端连接的线程
 */
class ServerThread(
    private val serverSocket: ServerSocket,
    val iServerListener: IServerListener? = null,
) : Thread(), IServerAction {
    // socket to be connected
    private val mSocketMap: ConcurrentHashMap<Client, SocketHandler> =
        ConcurrentHashMap<Client, SocketHandler>()

    override fun sendData(data: ByteArray?, client: Client) {
        data?.let {
            mSocketMap[client]?.putOutMessage(data)
        }
    }

    override fun broadcastData(data: ByteArray?) {
        if (!mSocketMap.isEmpty() && data != null && data.isNotEmpty()) {
            Log.d(TAG, "broadcastData: $data")
            for (handler in mSocketMap.values) {
                handler.putOutMessage(data)
            }
        }
    }

    override fun closeClient(client: Client) {
        mSocketMap[client]?.finish()
        mSocketMap.remove(client)
    }

    override fun closeServer() {
        mRunning = false
        Log.d(TAG, "finish: ")
        if (!mSocketMap.isEmpty()) {
            for (socketHandler in mSocketMap.values) {
                socketHandler.finish()
            }
            mSocketMap.clear()
        }

        SafeCloseUtil.close(mServerSocket)
        mServerSocket = null
        iServerListener?.onServerAlreadyShutdown(serverSocket.localPort)
    }


    val TAG = "ServerThread"

    @Volatile
    private var mServerSocket: ServerSocket? = null


    @Volatile
    private var mRunning = false

    init {
        mRunning = true
        mServerSocket = serverSocket
    }

    override fun run() {
        Log.d(TAG, "run:${currentThread().name} ")
        while (mRunning && mServerSocket != null && !mServerSocket!!.isClosed) {
            synchronized(ServerThread::class.java) {
                if (!mServerSocket!!.isClosed) {
                    try {
                        Log.d(TAG, "mServerSocket :${mServerSocket!!.isClosed}")
                        val socket = mServerSocket!!.accept()
                        Log.d(TAG, "run:a new client connected")
                        val remoteSocketAddress = socket.remoteSocketAddress as InetSocketAddress
                        val ip = remoteSocketAddress.address.hostAddress
                        val client = Client(socket, ip)
                        iServerListener?.onClientConnected(client)
                        mSocketMap[client]?.finish()
                        val socketHandler: SocketHandler =
                            object : SocketHandler(client) {

                                override fun parseData(bytes: ByteArray?, client: Client) {
                                    Log.d(TAG, "parseData:  ${String(bytes!!, Charset.defaultCharset())}")
                                    iServerListener?.parseData(bytes, client)
                                }

                                override fun disconnect(client: Client) {
                                    iServerListener?.onClientDisconnected(client)
                                }

                            }
                        mSocketMap[client] = socketHandler
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }
                }
            }
        }
    }


}